package win

import (
	"os"
	"path/filepath"
	"runtime"
	"syscall"
	"unsafe"

	"gitee.com/haifengat/goctp"
	ctp "gitee.com/haifengat/goctp/ctpdefine"
)

type Quote struct {
	goctp.HFQuote
	h        *syscall.DLL
	api, spi uintptr

    [[ range .On]]// [[ .Comment ]]
    _[[ .FuncName ]] func([[ range $i,$v := .FuncFields ]][[ if gt $i 0 ]], [[ end ]][[ .FieldName|trimStar ]] [[ .FieldType|ctp_type ]][[ end ]])
    [[ end]]
}

func (q *Quote) loadDll() {
	workPath, _ := os.Getwd()
	_, curFile, _, _ := runtime.Caller(1)
	dllPath := filepath.Dir(curFile)
	_ = os.Chdir(dllPath)
	q.h = syscall.MustLoadDLL("ctp_quote.dll")

	// 还原到之前的工作目录
	os.Chdir(workPath)
	//defer h.Release() // 函数结束后会释放导致后续函数执行失败
}

// 接口
func NewQuote() *Quote {
	q := new(Quote)

	// 主调函数封装 手动添加
	q.HFQuote.ReqConnect = func(addr string) {
		bs, _ := syscall.BytePtrFromString(addr)
		q.h.MustFindProc("qRegisterFront").Call(q.api, uintptr(unsafe.Pointer(bs)))
		q.h.MustFindProc("qInit").Call(q.api)
		// q.h.MustFindProc("Join").Call(q.api)
	}
	q.HFQuote.ReleaseAPI = func() {
		q.h.MustFindProc("qRelease").Call(q.api)
	}
	q.HFQuote.ReqUserLogin = func(f *ctp.CThostFtdcReqUserLoginField, i int) {
		q.h.MustFindProc("qReqUserLogin").Call(q.api, uintptr(unsafe.Pointer(&f)), uintptr(1))
	}
	q.HFQuote.ReqSubMarketData = func(instrument ...string) {
		ppInstrumentID := make([][]byte, len(instrument)) // [][]byte{[]byte(instrument)}
		for i := 0; i < len(instrument); i++ {
			copy(ppInstrumentID[i], []byte(instrument[i]))
		}
		q.h.MustFindProc("qSubscribeMarketData").Call(q.api, uintptr(unsafe.Pointer(&ppInstrumentID)), uintptr(len(instrument)))
	}

	// HFQuote 响应  手动添加即可增加新功能
	q._RtnDepthMarketData = func(f *ctp.CThostFtdcDepthMarketDataField) {
		q.HFQuote.RtnDepthMarketData(f)
	}
	q._RspUserLogin = func(f *ctp.CThostFtdcRspUserLoginField, i *ctp.CThostFtdcRspInfoField, n int, b bool) {
		q.HFQuote.RspUserLogin(f, i)
	}
	q._FrontConnected = func() {
		q.HFQuote.FrontConnected()
	}
	q._FrontDisconnected = func(n int) {
		q.HFQuote.FrontDisConnected(n)
	}

	q.HFQuote.Init() // 初始化

	q.loadDll()
	q.api, _, _ = q.h.MustFindProc("qCreateApi").Call()
	q.spi, _, _ = q.h.MustFindProc("qCreateSpi").Call()
	q.h.MustFindProc("qRegisterSpi").Call(q.api, uintptr(q.spi))

    [[ range .On ]]q.h.MustFindProc("qSetOn[[ .FuncName ]]").Call(q.spi, syscall.NewCallback(q.On[[ .FuncName ]]))
    [[ end ]]
	return q
}

[[ range .On ]]
// [[ .Comment ]]
func (q *Quote) On[[ .FuncName ]]([[ range $i, $v := .FuncFields ]][[ if gt $i 0]], [[ end ]][[ .FieldName|trimStar ]] [[ .FieldType|ctp_type]][[ end ]]) uintptr {
    if q._[[ .FuncName ]] != nil {    
	    q._[[ .FuncName ]]([[ range $i,$v := .FuncFields ]][[ if gt $i 0 ]], [[ end ]][[ .FieldName|trimStar ]][[ end ]])
    }
	return 0
}
[[ end ]]
